package com.zxt.dental_sys.Controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.zxt.dental_sys.model.AuthUserInfo;
import com.zxt.dental_sys.model.SysElementUserinfo;
import com.zxt.dental_sys.model.dto.LoginRequest;
import com.zxt.dental_sys.model.dto.OneData;
import com.zxt.dental_sys.model.vo.RestBean;
import com.zxt.dental_sys.service.AuthUserDetailService;
import com.zxt.dental_sys.service.impl.SysElementUserinfoServiceImpl;
import com.zxt.dental_sys.util.GenerationAccountUtil;
import com.zxt.dental_sys.util.JedisUtil;
import com.zxt.dental_sys.util.JwtUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @author 24862
 */
@RestController
@RequestMapping("api/auth")
@Slf4j
public class UserLoginController {

    @Resource
    JwtUtil jwtUtil;

    @Resource
    AuthenticationManager authenticationManager;

    @Resource
    AuthUserDetailService authUserDetailService;

    @Resource
    PasswordEncoder passwordEncoder;

    @Resource
    JedisUtil jedisUtil;

    @Resource
    GenerationAccountUtil generationAccountUtil;

    @Resource
    SysElementUserinfoServiceImpl userInfoService;


    /**
     * 携带参数Json
     * {
     * "username":"poxiaodi",
     * "password":"poxiaodi"
     * }
     */
    @PostMapping("login")
    public RestBean doLogin(@RequestBody LoginRequest request) {
        try {
            UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword());
            Authentication authentication = authenticationManager.authenticate(auth);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            SysElementUserinfo info = userInfoService.getOne(new QueryWrapper<SysElementUserinfo>().eq("username"
                    , userDetails.getUsername()));//通过用户名来获取该用户的所有登录信息
            String jwtToken = jwtUtil.getToken(info.getUserPk());//通过uuid来jwt生成获取token
            String userUUID = info.getUserPk();
            jedisUtil.setNewVal(2, userUUID, jwtToken);//通过userId来存储
            return RestBean.success(jwtToken);//返回jwt
        } catch (Exception e) {
            log.error(e.getMessage());
            log.error("username or password is not correct");
            return RestBean.failure(401, "登录失败");
        }
    }


    @RequestMapping("/updateTime")
    public RestBean updateUserUpdateTime(HttpServletRequest request) {
        String uuid = jwtUtil.getJwtUUID(request);
        SysElementUserinfo byId = userInfoService.getById(uuid);
        byId.setUpdateTime(new Date());
        return userInfoService.updateById(byId) ? RestBean.success(byId) : RestBean.failure(500, "server error");
    }

    //更新用户信息
    @RequestMapping("/updateUserInfo")
    public RestBean updateUserInfo(@RequestBody SysElementUserinfo userInfo, HttpServletRequest request) {
        String uuid = jwtUtil.getJwtUUID(request);
        SysElementUserinfo byId = userInfoService.getById(uuid);
        if (userInfo.getName() != null && !userInfo.getName().isEmpty()) {
            byId.setName(userInfo.getName());
        }
        if (userInfo.getTel() != null && !userInfo.getTel().isEmpty()) byId.setTel(userInfo.getTel());
        if (userInfo.getMail() != null && !userInfo.getMail().isEmpty()) byId.setMail(userInfo.getMail());
        byId.setSexs(userInfo.getSexs());
        if (userInfo.getBornDate() != null && !userInfo.getBornDate().toString().isEmpty())
            byId.setBornDate(userInfo.getBornDate());
        byId.setUpdateTime(new Date());
        return userInfoService.updateById(byId) ? RestBean.success(byId) : RestBean.failure(500, "server error");
    }


    @RequestMapping("updateImg")
    public RestBean updateUserImg(@RequestBody OneData oneData, HttpServletRequest request) {
        String uuid = jwtUtil.getJwtUUID(request);
        SysElementUserinfo byId = userInfoService.getById(uuid);
        byId.setHeadimgurl(oneData.getData().toString());
        byId.setUpdateTime(new Date());
        return userInfoService.updateById(byId) ? RestBean.success(byId) : RestBean.failure(500, "server error");
    }


    /**
     * 传递参数包含
     * {
     * "username":"test233",
     * "password":"test",
     * "email":"test",
     * "role":"admin",
     * "account":"",
     * "demo":"",
     * "address":"",
     * "bornDate":"2023-10-04",
     * "img":"",
     * "qqNum":"",
     * "wxNum":"",
     * "sex":"男"
     * }
     * <p>
     * {
     * username,
     * password,
     * email,
     * roles
     * }
     *
     * @param user
     * @return
     */

    @PostMapping("/register")
    public RestBean userRegister(@RequestBody SysElementUserinfo user, @RequestParam String code) {
        if (user.getUsername() == null || user.getUsername().isEmpty() || user.getPassword() == null || user.getPassword().isEmpty()) {
            return RestBean.failure(401, "用户名或密码不能为空");
        }
        if (!(code.equals("admin")  || code.equals("医生")  || code.equals("患者"))) {
            return RestBean.failure(401, "角色异常");
        }

        String password = passwordEncoder.encode(user.getPassword());
        //存储数据库中的密码要进行加密处理
        user.setPassword(password);
        user.setRoles(code);
        long userCount = userInfoService.count(new QueryWrapper<SysElementUserinfo>().eq("username", user.getUsername()));   //用户名不可重复
        if (userCount == 0L) {
            try {
                UUID uuid = UUID.randomUUID();
                user.setUserPk(String.valueOf(uuid));//UUID生成唯一标识
                user.setInputTime(new Date());
                if (user.getUsername() == null || user.getUsername().isEmpty()) {
                    user.setUsername(generationAccountUtil.generation(user.getUsername()));
                }
                authUserDetailService.insertUser(user);
                String jwtToken = jwtUtil.getToken(user.getUserPk());//这里也采用uuid返回jwt
                return RestBean.success(jwtToken);
            } catch (Exception e) {
                log.info(e.getMessage());
            }
        } else {
            log.info("Username:" + user.getUsername() + "is exists");
            return RestBean.failure(403, "该用户已存在，请重新输入用户名");
        }

        return RestBean.failure(403, "注册失败");
    }

    @RequestMapping("update/user")
    public RestBean updateUserInfoByUserSelf(@RequestBody SysElementUserinfo userLoginInfo, HttpServletRequest httpServletRequest) {
        log.info(userLoginInfo.toString());
        try {
            String uuid = jwtUtil.getJwtUUID(httpServletRequest);//获取uuid
            log.info(uuid);
            long count = userInfoService.count(new QueryWrapper<SysElementUserinfo>().eq("user_pk", uuid)
                    .eq("is_enabled", 1).eq("is_deleted", 0));

            if (count == 1) {//用来查看是否存在该用户
                SysElementUserinfo info = userInfoService.getById(uuid);//通过请求人的uuid来获取
                try {
                    long count1 = userInfoService.count(new QueryWrapper<SysElementUserinfo>()
                            .eq("username", userLoginInfo.getUsername())
                    );
                    if (count1 == 1){
                        SysElementUserinfo one = userInfoService.getOne(new QueryWrapper<SysElementUserinfo>()
                                .eq("username", userLoginInfo.getUsername())
                        );
                        if (!one.getUserPk().equals(uuid) ){
                            return RestBean.failure(400,"该用户名以重复，请重新设置");
                        }
                    }
                }catch (Exception e){
                    return RestBean.failure(500,"服务异常");
                }

                userLoginInfo.setUpdateTime(new Date());//设置更新时间
                userLoginInfo.setUserPk(uuid);//来获取jwt里面的uuid
                try {
                    if (userLoginInfo.getPassword() != "" && userLoginInfo.getPassword() != null){
                        userLoginInfo.setPassword(passwordEncoder.encode(userLoginInfo.getPassword()));
                    }else{
                        userLoginInfo.setPassword(info.getPassword());//这里不能直接修改密码，修改密码到必须专门的接口来修改
                    }
                }catch (Exception e){
                    userLoginInfo.setPassword(info.getPassword());//这里不能直接修改密码，修改密码到必须专门的接口来修改
                }
                userLoginInfo.setInputTime(info.getInputTime());//账号创建时间不可修改
                userLoginInfo.setIsEnabled(info.getIsEnabled());//账号状态不可从这里修改,有专门的接口来进行初始化操作。
                userLoginInfo.setRoles(info.getRoles());//角色信息不可以修改
                userLoginInfo.setIsDeleted(info.getIsDeleted());//用户是否注销
                boolean updateById = userInfoService.updateById(userLoginInfo);
                if (updateById) {
                    return RestBean.success(userLoginInfo, 1L);
                }
                return RestBean.failure(500, "更新失败");
            } else {
                return RestBean.failure(403, "token error | user is unEnable");//不存在该uuid
            }
        } catch (Exception e) {
            log.info(e.getMessage());
            return RestBean.failure(500, "更新用户信息失败");
        }
    }

    @RequestMapping("/charge/name")
    public RestBean chargeUsername(HttpServletRequest request, String username) {
        String uuid = jwtUtil.getJwtUUID(request);
        long count = userInfoService.count(new QueryWrapper<SysElementUserinfo>().eq("username", username));
        if (count > 0) {
            return RestBean.failure(400, "该账号已重复，请更换其他的账号名试试");
        }
        SysElementUserinfo info = userInfoService.getById(uuid);
        info.setUsername(username);
        info.setUpdateTime(new Date());
        if (userInfoService.updateById(info)) {
            return RestBean.success(info);
        }
        return RestBean.failure(500, "更新账号失败");
    }

    //    @RequestMapping("/password/forget")
    public RestBean updateByEmail(@RequestBody LoginRequest request, String code) throws Exception {
        SysElementUserinfo userLoginInfo = userInfoService.getOne(new QueryWrapper<SysElementUserinfo>().eq("username", request.getUsername()));
        if (userLoginInfo != null) {
            if (jedisUtil.exist(4, userLoginInfo.getMail())) {
                if (jedisUtil.getValue(4, userLoginInfo.getMail()).equals(code)) {
                    userLoginInfo.setPassword(passwordEncoder.encode(request.getPassword()));//更新密码
                    userLoginInfo.setUpdateTime(new Date());//更新时间
                    return userInfoService.updateById(userLoginInfo) ? RestBean.success(jwtUtil.getToken(request.getUsername()), 1L) : RestBean.failure(500, "更新失败");
                }
                return RestBean.failure(403, "验证码错误");
            }
            return RestBean.failure(403, "请重新获取验证码");
        }
        return RestBean.failure(403, "没有该用户");
    }


    //    @RequestMapping("update/admin")//要返回该用户的uuid
    public RestBean updateUserInfoByAdmin(@RequestBody SysElementUserinfo userLoginInfo) {
        try {
            boolean flag = false;//定义一个标识符来查看是否存在该用户的uuid
            List<SysElementUserinfo> userLoginInfos = userInfoService.list();
            for (SysElementUserinfo loginInfo : userLoginInfos) {
                if (loginInfo.getUsername().equals(userLoginInfo.getUsername())) {
                    return RestBean.failure(403, "用户名已存在");
                }
                if (userLoginInfo.getUserPk().equals(loginInfo.getUserPk())) {
                    flag = true;
                }
            }//查看用户名是否存在
            if (flag && (userInfoService.updateById(userLoginInfo))) {//如果更新成功那么返回
                return RestBean.success(userInfoService.getById(userLoginInfo.getUserPk()), 1L);
            }
            return RestBean.failure(500, "更新失败");
        } catch (Exception e) {
            log.info(e.getMessage());
            return RestBean.failure(500, "更新用户信息失败");
        }
    }


    @PostMapping("check")//更新登陆状态，如果已经过时，那么需要重新登陆
    public RestBean checkRepeat(HttpServletRequest httpServletRequest) throws Exception {
        String uuid = jwtUtil.getJwtUUID(httpServletRequest);
        log.info(uuid);
        if (uuid == null) {
            return RestBean.failure(403, "请重新登录");
        }
        SysElementUserinfo info = userInfoService
                .getOne(new QueryWrapper<SysElementUserinfo>().eq("user_pk", uuid));
        if (info == null) {
            return RestBean.failure(403, "没有此用户");
        }
        String token = jwtUtil.getToken(uuid);
        return RestBean.success(token, 1L);
    }

    @RequestMapping("/check/{roles}")
    public RestBean updateTokenByUserAndRoles(@PathVariable String roles
            ,HttpServletRequest request) throws Exception {
        String uuid = jwtUtil.getJwtUUID(request);
        log.info(uuid);
        if (uuid == null) {
            return RestBean.failure(403, "请重新登录");
        }
        SysElementUserinfo info = userInfoService.getOne(new QueryWrapper<SysElementUserinfo>().eq("user_pk", uuid));
        if (info == null) {
            return RestBean.failure(403, "没有此用户");
        }
        if(!info.getRoles().equals(roles)){
            return RestBean.failure(400,"角色异常");
        }
        String token = jwtUtil.getToken(uuid);
        return RestBean.success(token, 1L);
    }


    @RequestMapping("/userinfo")
    public RestBean getUserInfo(HttpServletRequest request) {
        String uuid = jwtUtil.getJwtUUID(request);
        if (uuid == null) {
            return RestBean.failure(500, "没有此用户");
        }
        long count = userInfoService.count(new QueryWrapper<SysElementUserinfo>().eq("user_pk", uuid));
        if (count == 0L) {
            return RestBean.failure(403, "没有此用户");
        }
        try {
            AuthUserInfo authUserInfo = new AuthUserInfo();
            SysElementUserinfo info = userInfoService.getById(uuid);
            BeanUtils.copyProperties(authUserInfo, info);
            authUserInfo.setRoleList(Collections.singletonList(info.getRoles()));
            return RestBean.success(authUserInfo);
        } catch (Exception e) {
            return RestBean.failure(400, "");
        }

    }

    @RequestMapping("test")
    public String test(String name, HttpServletRequest request) {
        System.out.println(request.getRemoteHost());
        System.out.println(request.getRemoteAddr());
        System.out.println(request.toString());
        return "hello world" + name;
    }

    @RequestMapping("/get-userinfo")
    public RestBean getUserInfoById(String userId) {
        long count = userInfoService.count(new QueryWrapper<SysElementUserinfo>().eq("user_pk", userId));
        if (count == 0L) {
            return RestBean.failure(400, "不存在该用户");
        }
        return RestBean.success(userInfoService.getById(userId));
    }

    @RequestMapping("/isAdmin")
    public RestBean isAdmin(HttpServletRequest request) {
        return RestBean.success("hello world");
    }

    @RequestMapping("/userInfos")
    public RestBean userInfos() {
        return RestBean.success(userInfoService.list());
    }


    @RequestMapping("disabled/{id}/{val}")
    public RestBean isDisableUser(@PathVariable String id, @PathVariable int val) {
        try {
            SysElementUserinfo byId = userInfoService.getById(id);
            byId.setIsEnabled(val);
            return userInfoService.updateById(byId) ? RestBean.success(byId) : RestBean.failure(500, "server error");
        } catch (Exception e) {
            log.info(e.getMessage());
            return RestBean.failure(500, "server error");
        }
    }

    /**
     * 分页查询用户信息
     *
     * @param name
     * @param page
     * @param size
     * @param roles
     * @return
     */
    @RequestMapping("/list/{page}/{size}")
    public RestBean queryList(String name, @PathVariable int page, @PathVariable int size, String roles) {
        PageInfo<SysElementUserinfo> sysElementUserinfoPageInfo = userInfoService.queryUserList(page, size, name, roles);
        return RestBean.success(sysElementUserinfoPageInfo);
    }

    @RequestMapping("/list/roles")
    public RestBean listOfRoles(String roles){
        return RestBean.success(userInfoService.list(new QueryWrapper<SysElementUserinfo>()
                .eq("is_deleted",0)
                .eq("roles",roles)
        ));
    }

    @RequestMapping("/addNewUserInfo")
    public RestBean addUserInfo(@RequestBody SysElementUserinfo userinfo) {
        String uuid = UUID.randomUUID().toString();
        userinfo.setUserPk(uuid);
        if (userinfo.getUsername() == "" || userinfo.getPassword() == "") {
            return RestBean.failure(400, "账号或密码不能为空");
        }
        if (!(userinfo.getRoles() != "患者" && userinfo.getRoles() != "admin" && userinfo.getRoles() != "医生")) {
            return RestBean.failure(400, "角色异常");
        }
        try {
            SysElementUserinfo one = userInfoService.getOne(new QueryWrapper<SysElementUserinfo>()
                    .eq("username", userinfo.getUsername())
            );
        } catch (Exception e) {
            return RestBean.failure(400, "该用户名已存在，请更改用户名");
        }
        userinfo.setPassword(passwordEncoder.encode(userinfo.getPassword()));
        userinfo.setInputTime(new Date());
        return userInfoService.save(userinfo) ?
                RestBean.success(userinfo) : RestBean.failure(500, "server error");
    }

    @RequestMapping("/updateUserInfos")
    public RestBean updateUserInfos(@RequestBody SysElementUserinfo userinfo) {
        try {
            if (userinfo.getUsername() == "" ) {
                return RestBean.failure(400, "账号不能为空");
            }
            SysElementUserinfo byId = userInfoService.getById(userinfo.getUserPk());
            byId.setUpdateTime(new Date());
            try {
                SysElementUserinfo one = userInfoService.getOne(new QueryWrapper<SysElementUserinfo>()
                        .eq("username", userinfo.getUsername())
                );
                if (!Objects.equals(one.getUserPk(), userinfo.getUserPk())) {
                    return RestBean.failure(400, "用户名重复");
                }
            } catch (Exception e) {
            }
            byId.setUsername(userinfo.getUsername());
            try {
                if (userinfo.getPassword() != "") {
                    byId.setPassword(passwordEncoder.encode(userinfo.getPassword()));
                }
            } catch (Exception e) {
            }
            byId.setName(userinfo.getName() != null ? userinfo.getName() : "");
            byId.setTel(userinfo.getTel() != null ? userinfo.getTel() : "");
            byId.setMail(userinfo.getMail() != null ? userinfo.getMail() : "");
            byId.setBornDate(userinfo.getBornDate() != null ? userinfo.getBornDate() : null);
            byId.setRoles(userinfo.getRoles() != null ? userinfo.getRoles() : "");
            byId.setSexs(userinfo.getSexs() != null ? userinfo.getSexs() : "");
            byId.setIdentificationCard(userinfo.getIdentificationCard() != null ? userinfo.getIdentificationCard() : "");
            byId.setHeadimgurl(userinfo.getHeadimgurl() != null ? userinfo.getHeadimgurl() : "");
            return userInfoService.updateById(byId)?RestBean.success(byId)
                    :RestBean.failure(500,"server error");

        } catch (Exception e) {
            return RestBean.failure(400, "用户信息异常");
        }
    }


}
